package com.inspur.edp.bef.bizentity;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.inspur.edp.bef.bizentity.commonstructure.BeCommonStructureUtil;
import com.inspur.edp.bef.bizentity.json.element.BizElementSerializer;
import com.inspur.edp.bef.bizentity.operation.collection.DeterminationCollection;
import com.inspur.edp.bef.bizentity.operation.collection.ValidationCollection;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.CommonDtmCollection;
import com.inspur.edp.cef.designtime.api.collection.CommonValCollection;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.entity.commonstructure.CefCommonStructureUtil;
import com.inspur.edp.das.commonmodel.entity.GspCommonElement;
import com.inspur.edp.das.commonmodel.entity.element.ElementCodeRuleConfig;
import com.inspur.edp.das.commonmodel.entity.element.GspCommonAssociation;
import com.inspur.edp.bef.bizentity.beenum.RequiredCheckOccasion;
import com.inspur.edp.bef.bizentity.json.element.BizElementDeserializer;
import lombok.Getter;
import lombok.Setter;
// import Inspur.Gsp.Udt.DesignTime.Api.Entity.*;


/**
 * 业务实体字段实体类
 *<p>
 * 新建普通字段
 * <blockquote><pre>
 *     public GspBizEntityElement createElement() {
 *         GspBizEntityElement ele = new GspBizEntityElement();
 *         ele.setID(Guid.newGuid().toString());
 *         ele.setCode("newEleCode");
 *         ele.setName("新增字段");
 *         ele.setLabelID(ele.getCode());
 *         ele.setLength(36);
 *         ele.setPrecision(4);
 *         ele.setDefaultValue("DefaultValue");
 *         ele.setObjectType(GspElementObjectType.None);
 *         ele.setMDataType(GspElementDataType.Decimal);
 *         return ele;
 *     }
 * </pre></blockquote>
 *<p>
 * 新建枚举字段
 * <blockquote><pre>
 *       public  GspBizEntityElement createElementWithEnumValues() {
 *         GspBizEntityElement ele = new GspBizEntityElement();
 *         //GspBizEntityElement ele = new GspBizEntityElement();
 *         ele.setID(Guid.newGuid().toString());
 *         ele.setCode("newEnumCode");
 *         ele.setName("枚举字段");
 *         ele.setObjectType(GspElementObjectType.Enum);
 *         GspEnumValue enum1 = new GspEnumValue();
 *         enum1.setName("在职");
 *         enum1.setValue("0");
 *         enum1.setI18nResourceInfoPrefix("enum1.I18nResourceInfoPrefix");
 *         GspEnumValue enum2 = new GspEnumValue();
 *         enum2.setName("离职");
 *         enum2.setValue("1");
 *         enum2.setI18nResourceInfoPrefix("enum2.I18nResourceInfoPrefix");
 *         ele.getContainEnumValues().addEnumValue(enum1);
 *         ele.getContainEnumValues().addEnumValue(enum2);
 *         return ele;
 *     }
 * </pre></blockquote>
 *<p>
 * 新建关联字段
 * <blockquote><pre>
 *       public  GspBizEntityElement createElementWithAssos() {
 *         GspBizEntityElement ele = new GspBizEntityElement();
 *         ele.setID(Guid.newGuid().toString());
 *         ele.setCode("newAssos");
 *         ele.setName("关联字段");
 *         ele.setObjectType(GspElementObjectType.Association);
 *         GspCommonAssociation asso1 = new GspCommonAssociation();
 *         asso1.setId(Guid.newGuid().toString());
 *         asso1.setAssSendMessage("关联的提示错误信息。");
 *
 *         //设置字段关联关系，并将关联关系添加至关联
 *         GspAssociationKey ass = new GspAssociationKey();
 *         ass.setSourceElement("SourceElementID");
 *         ass.setTargetElement("TargetElementID");
 *         asso1.getKeyCollection().add(ass);
 *
 *         //设置当前be上字段与目标be上的字段相关联
 *         GspBizEntityElement refElemenet = new GspBizEntityElement();
 *         ele.setID(Guid.newGuid().toString());
 *         ele.setCode("newAssoCode1");
 *         ele.setName("关联字段1");
 *         refElemenet.setIsRefElement(true);
 *         refElemenet.setParentAssociation(asso1);
 *         refElemenet.setRefElementId("目标be上字段的id");
 *
 *         //设置字段为关联带出字段
 *         GspBizEntityElement refEle = new GspBizEntityElement();
 *         ele.setID(Guid.newGuid().toString());
 *         ele.setCode("newAssoCode2");
 *         ele.setName("关联字段2");
 *         refEle.setParentAssociation(asso1);
 *         asso1.getRefElementCollection().add(refEle);
 *         ele.getChildAssociations().add(asso1);
 *         return ele;
 *     }
 * </pre></blockquote>
 *
 */
// C# TO JAVA CONVERTER TODO TASK: Java annotations will not correspond to .NET
// attributes:
// [, System.Diagnostics.debuggerDisplay("Code={Code}, ID={ID},
// BelongObject={BelongObject.getCode()}")]
@JsonDeserialize(using = BizElementDeserializer.class)
@JsonSerialize(using = BizElementSerializer.class)
public class GspBizEntityElement extends GspCommonElement implements Cloneable {
	private transient RequiredCheckOccasion requiredCheckOccasion = RequiredCheckOccasion.All;

	// region 属性
	/**
	 * 是否默认为空值
	 */
	private boolean isDefaultNull=false;

	public boolean getIsDefaultNull(){
		return isDefaultNull;
	}

	public void setIsDefaultNull(boolean value){
		isDefaultNull=value;
	}
	/**
	 * 计算表达式
	 * <p>
	 * 不采用封装类的原因是有可能会在代码中修改，如果记录Element，依赖的Element用户就不好处理了
	 */
	private transient String privateCalculationExpress;

	public final String getCalculationExpress() {
		return privateCalculationExpress;
	}

	public final void setCalculationExpress(String value) {
		privateCalculationExpress = value;
	}

	/**
	 * 验证表达式
	 */
	private transient String privateValidationExpress;

	public final String getValidationExpress() {
		return privateValidationExpress;
	}

	public final void setValidationExpress(String value) {
		privateValidationExpress = value;
	}

	private String rtElementConfigId;

	public String getRtElementConfigId() {
		return rtElementConfigId;
	}

	public void setRtElementConfigId(String rtElementConfigId) {
		this.rtElementConfigId = rtElementConfigId;
	}
	///// <summary>
	///// 是否只读
	///// </summary>
	///// <remarks>只读属性用于控制BEF外部提交的变更不被系统接受，只有BE内部action和状态管理可以修改此属性</remarks>
	// public bool Readonly { get; set; }

	/**
	 * 必填检查时机
	 */
	public final RequiredCheckOccasion getRequiredCheckOccasion() {
		return requiredCheckOccasion;
	}

	public final void setRequiredCheckOccasion(RequiredCheckOccasion value) {
		requiredCheckOccasion = value;
	}

	@Getter
	@Setter
	private CommonDtmCollection valueChangedDtms;

	@Getter
	@Setter
	private CommonDtmCollection computationDtms;

	@Getter
	@Setter
	private CommonValCollection valueChangedVals;
	// endregion

	// region 方法
	// private UnifiedDataTypeDef privateUnifiedDataType;
	// public final UnifiedDataTypeDef getUnifiedDataType()
	// {
	// return privateUnifiedDataType;
	// }
	// public final void setUnifiedDataType(UnifiedDataTypeDef value)
	// {
	// privateUnifiedDataType = value;
	// }

	public final void mergeWithDependentElement(GspBizEntityElement dependentElement) {
		if (getIsRef()) {
			mergeElementBaseInfo(dependentElement);
		}
		mergeChildAssociations(dependentElement, getIsRef());
	}

	private void mergeElementBaseInfo(GspBizEntityElement dependentElement) {
		setCode(dependentElement.getCode());
		setName(dependentElement.getName());
		setLabelID(dependentElement.getLabelID());
		setMDataType(dependentElement.getMDataType());
		setDefaultValue(dependentElement.getDefaultValue());
		setDefaultValueType(dependentElement.getDefaultValueType());
		setLength(dependentElement.getLength());
		setPrecision(dependentElement.getPrecision());
		setObjectType(dependentElement.getObjectType());
		// ColumnID = dependentElement.ColumnID;
		setIsVirtual(dependentElement.getIsVirtual());
		setIsRequire(dependentElement.getIsRequire());
		setIsCustomItem(dependentElement.getIsCustomItem());
		setIsRefElement(dependentElement.getIsRefElement());
		setRefElementId(dependentElement.getRefElementId());
		setIsMultiLanguage(dependentElement.getIsMultiLanguage());
		setBelongModelID(dependentElement.getBelongModelID());

		setContainEnumValues(dependentElement.getContainEnumValues());
		mergeBillCode(dependentElement.getBillCodeConfig());

		setReadonly(dependentElement.getReadonly());
		setRequiredCheckOccasion(dependentElement.getRequiredCheckOccasion());
		setCalculationExpress(dependentElement.getCalculationExpress());
		setValidationExpress(dependentElement.getValidationExpress());

	}

	private void mergeBillCode(ElementCodeRuleConfig dependentConfig) {
		if (dependentConfig == null) {
			return;
		}
		super.setBillCodeConfig(dependentConfig.clone());
	}

	private void mergeChildAssociations(GspBizEntityElement dependentElement, boolean isRef) {
		if (getChildAssociations() == null || getChildAssociations().size() < 1) {
			return;
		}
		for (GspAssociation childAssociation : getChildAssociations()) {
			GspCommonAssociation dependentAssociation = (GspCommonAssociation) (dependentElement.getChildAssociations()
					.getItem(childAssociation.getId()));
			mergeChildAssociation((GspCommonAssociation) childAssociation, dependentAssociation, isRef);
		}
	}

	private void mergeChildAssociation(GspCommonAssociation childAssociation, GspCommonAssociation dependentAssociation,
	                                   boolean isRef) {
		if (isRef) {
			mergeAssociationBaseInfo(childAssociation, dependentAssociation);
		}
		mergeRefElements(childAssociation, dependentAssociation);
	}

	private void mergeAssociationBaseInfo(GspCommonAssociation childAssociation, GspCommonAssociation dependentAssociation) {
		childAssociation.setRefModelID(dependentAssociation.getRefModelID());
		childAssociation.setRefModelCode(dependentAssociation.getRefModelCode());
		childAssociation.setRefModelName(dependentAssociation.getRefModelName());
		childAssociation.setWhere(dependentAssociation.getWhere());
		childAssociation.setAssSendMessage(dependentAssociation.getAssSendMessage());
		childAssociation.setForeignKeyConstraintType(dependentAssociation.getForeignKeyConstraintType());
		childAssociation.setDeleteRuleType(dependentAssociation.getDeleteRuleType());
		for (com.inspur.edp.cef.designtime.api.element.GspAssociationKey GspAssociationKey : dependentAssociation.getKeyCollection()) {
			childAssociation.getKeyCollection().addAssociation(GspAssociationKey);
		}

	}

	private void mergeRefElements(GspCommonAssociation childAssociation, GspCommonAssociation dependentAssociation) {
		if (childAssociation.getRefElementCollection() == null || childAssociation.getRefElementCollection().size() < 1) {
			return;
		}
		for (IGspCommonField refElement : childAssociation.getRefElementCollection()) {
			GspBizEntityElement dependentRefElement = (GspBizEntityElement) dependentAssociation.getRefElementCollection()
					.getItem(refElement.getID());
			((GspBizEntityElement) refElement).mergeWithDependentElement(dependentRefElement);
		}
	}
	//endregion

	// region Property
	@Override
	protected CefCommonStructureUtil getCefCommonStructureUtil() {
		return BeCommonStructureUtil.getInstance();
	}

	// endregion
}